/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
 * 
 * Use is subject to license terms.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * 
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ************************************************************************/

using System;
using System.Xml.Linq;
using AODL.Document.Import.OpenDocument.NodeProcessors;
using AODL.Document.Styles;

namespace AODL.Document.Content.Text
{
    /// <summary>
    /// Represent a formated Text e.g bold, italic, underline etc.
    /// </summary>
    public class FormatedText : IHtml, IText, ITextContainer, ICloneable
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FormatedText"/> class.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <param name="node">The node.</param>
        public FormatedText(IDocument document, XElement node)
        {
            Document = document;
            Node = node;
            InitStandards();
        }

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="document">The content object to which the formated text belongs to.</param>
        /// <param name="name">The stylename which should be referenced with this FormatedText object.</param>
        /// <param name="text">The Displaytext.</param>
        public FormatedText(IDocument document, string name, string text)
        {
            Document = document;
            Node = new XElement(Ns.Text + "span");
            Node.SetAttributeValue(Ns.Text + "style-name", name);
            InitStandards();

            Text = text;
            Style = new TextStyle(Document, name);
            Document.Styles.Add(Style);
        }

// Phil Jollans 18-Feb-2008
// Additional construcor

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="document">The content object to which the formated text belongs to.</param>
        /// <param name="textstyle">An existing TextStyle object.</param>
        /// <param name="text">The Displaytext.</param>
        public FormatedText(IDocument document, IStyle textstyle, string text)
        {
            Document = document;
            Node = new XElement(Ns.Text + "span");
            Node.SetAttributeValue(Ns.Text + "style-name", textstyle.StyleName);
            InitStandards();

            Text = text;
            Style = textstyle;
        }

        /// <summary>
        /// Gets or sets the text style.
        /// </summary>
        /// <value>The text style.</value>
        public TextStyle TextStyle
        {
            get { return (TextStyle) Style; }
            set { Style = value; }
        }

        /// <summary>
        /// Inits the standards.
        /// </summary>
        private void InitStandards()
        {
            TextContent = new ITextCollection();
            TextContent.Inserted += TextContent_Inserted;
            TextContent.Removed += TextContent_Removed;
        }

        /// <summary>
        /// Texts the content_ inserted.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="value">The value.</param>
        private void TextContent_Inserted(int index, object value)
        {
            Node.Add(((IText) value).Node);
        }

        /// <summary>
        /// Texts the content_ removed.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="value">The value.</param>
        private static void TextContent_Removed(int index, object value)
        {
            ((IText) value).Node.Remove();
        }

        #region ICloneable Member

        /// <summary>
        /// Create a deep clone of this FormatedText object.
        /// </summary>
        /// <remarks>A possible Attached Style wouldn't be cloned!</remarks>
        /// <returns>
        /// A clone of this object.
        /// </returns>
        public object Clone()
        {
            FormatedText formatedTextClone = null;

            if (Document != null && Node != null)
            {
                TextContentProcessor tcp = new TextContentProcessor();
                formatedTextClone = tcp.CreateFormatedText(
                    Document, new XElement(Node));
            }

            return formatedTextClone;
        }

        #endregion

        #region IHtml Member

        /// <summary>
        /// Return the content as Html string
        /// </summary>
        /// <returns>The html string</returns>
        public string GetHtml()
        {
            string style = ((TextStyle) Style).TextProperties.GetHtmlStyle();
            string html = "<span ";
            string text = GetTextWithHtmlControl();

            if (style.Length > 0)
                html = html + style + ">\n";
            else
                html += ">\n";

            if (text.Length > 0)
                html += text;

            html += "</span>\n";

            html = GetSubOrSupStartTag() + html + GetSubOrSupEndTag();

            return html;
        }

        /// <summary>
        /// Gets the text with HTML controls
        /// as Tab as &amp;nbsp; and line-break as br tag
        /// </summary>
        /// <returns>The string</returns>
        private string GetTextWithHtmlControl()
        {
            string text = "";

            foreach (XNode node in Node.Nodes())
            {
                if (node is XElement)
                {
                    if (((XElement) node).Name.LocalName == "tab")
                        text += "&nbsp;&nbsp;&nbsp;";
                    else if (((XElement) node).Name.LocalName == "line-break")
                        text += "<br>";
                    //				else if (((XElement)node).Name.LocalName == "s")
                    //					text	+= WhiteSpace.GetWhiteSpaceHtml(node.OuterXml);
                }
                else if (node is XText && ((XText) node).Value.Length > 0)
                    text += ((XText) node).Value;
            }

            return text;
        }

        /// <summary>
        /// Gets the sub or sup start tag.
        /// </summary>
        /// <returns></returns>
        private string GetSubOrSupStartTag()
        {
            if (((TextStyle) Style).TextProperties.Position != null)
                if (((TextStyle) Style).TextProperties.Position.Length > 0)
                    if (((TextStyle) Style).TextProperties.Position.ToLower().StartsWith("sub"))
                        return "<sub>";
                    else
                        return "<sup>";

            return "";
        }

        /// <summary>
        /// Gets the sub or sup end tag.
        /// </summary>
        /// <returns></returns>
        private string GetSubOrSupEndTag()
        {
            if (((TextStyle) Style).TextProperties.Position != null)
                if (((TextStyle) Style).TextProperties.Position.Length > 0)
                    if (((TextStyle) Style).TextProperties.Position.ToLower().StartsWith("sub"))
                        return "</sub>";
                    else
                        return "</sup>";

            return "";
        }

        #endregion

        #region IText Member

        private IStyle _style;

        /// <summary>
        /// The node that represent the text content.
        /// </summary>
        /// <value></value>
        public XElement Node { get; set; }

        /// <summary>
        /// Gets or sets the node.
        /// </summary>
        /// <value>The node.</value>
        XNode IContent.Node
        {
            get { return Node; }
            set { Node = (XElement) value; }
        }

        /// <summary>
        /// Use this if use text without control character,
        /// otherwise use the the TextColllection TextContent. 
        /// </summary>
        /// <value></value>
        public string Text
        {
            get { return Node.Value; }
            set { Node.Value = value; }
        }

        /// <summary>
        /// The document to which this text content belongs to.
        /// </summary>
        /// <value></value>
        public IDocument Document { get; set; }

        /// <summary>
        /// The style which is referenced with this text object.
        /// This is null if no style is available.
        /// </summary>
        /// <value></value>
        public IStyle Style
        {
            get { return _style; }
            set
            {
                StyleName = value.StyleName;
                _style = value;
            }
        }

        /// <summary>
        /// The style name which is used for the referenced style.
        /// This is null is no  style is available.
        /// </summary>
        /// <value></value>
        public string StyleName
        {
            get { return (string) Node.Attribute(Ns.Text + "style-name"); }
            set { Node.SetAttributeValue(Ns.Text + "style-name", value); }
        }

        #endregion

        #region ITextContainer Member

        private ITextCollection _textContent;

        /// <summary>
        /// All Content objects have a Text container. Which represents
        /// his Text this could be SimpleText, FormatedText or mixed.
        /// </summary>
        /// <value></value>
        public ITextCollection TextContent
        {
            get { return _textContent; }
            set
            {
                if (_textContent != null)
                    foreach (IText text in _textContent)
                        text.Node.Remove();

                _textContent = value;

                if (_textContent != null)
                    foreach (IText text in _textContent)
                        Node.Add(text.Node);
            }
        }

        #endregion
    }
}

/*
 * $Log: FormatedText.cs,v $
 * Revision 1.4  2008/04/29 15:39:46  mt
 * new copyright header
 *
 * Revision 1.3  2008/04/10 17:33:16  larsbehr
 * - Added several bug fixes mainly for the table handling which are submitted by Phil  Jollans
 *
 * Revision 1.2  2007/04/08 16:51:23  larsbehr
 * - finished master pages and styles for text documents
 * - several bug fixes
 *
 * Revision 1.1  2007/02/25 08:58:38  larsbehr
 * initial checkin, import from Sourceforge.net to OpenOffice.org
 *
 * Revision 1.3  2006/02/02 21:55:59  larsbm
 * - Added Clone object support for many AODL object types
 * - New Importer implementation PlainTextImporter and CsvImporter
 * - New tests
 *
 * Revision 1.2  2006/01/29 18:52:14  larsbm
 * - Added support for common styles (style templates in OpenOffice)
 * - Draw TextBox import and export
 * - DrawTextBox html export
 *
 * Revision 1.1  2006/01/29 11:28:22  larsbm
 * - Changes for the new version. 1.2. see next changelog for details
 *
 * Revision 1.4  2005/12/12 19:39:17  larsbm
 * - Added Paragraph Header
 * - Added Table Row Header
 * - Fixed some bugs
 * - better whitespace handling
 * - Implmemenation of HTML Exporter
 *
 * Revision 1.3  2005/11/20 17:31:20  larsbm
 * - added suport for XLinks, TabStopStyles
 * - First experimental of loading dcuments
 * - load and save via importer and exporter interfaces
 *
 * Revision 1.2  2005/10/08 08:19:25  larsbm
 * - added cvs tags
 *
 */